package bblrtc

import (
	"time"
)

const (
	INIT = iota //0
	WAIT_ANSWER
	CALLING
	END
)

func new_rtc_session(caller, callee *Peer) *RTCSession {
	rtcsess := &RTCSession{
		Sid:             &caller.Sid,
		Caller:          caller,
		Callee:          callee,
		CallerCandidate: make(chan *Message, 20),
		CalleeCandidate: make(chan *Message, 20),
		State:           INIT,
		closeNotify:     make(chan bool),
	}
	caller.rtcsession = rtcsess
	callee.rtcsession = rtcsess
	caller.Calling()
	callee.Calling()
	caller.router.AddRTCSession(rtcsess)
	syslog.Println("创建RTC会话", caller.Member, "->", callee.Member)
	return rtcsess
}

type RTCSession struct {
	Sid             *string       //呼叫发起者会话ID
	Caller          *Peer         //主叫
	Callee          *Peer         //被叫
	CallerCandidate chan *Message //主叫方Candidate
	CalleeCandidate chan *Message //被叫方Candidate
	State           int           //会话状态
	closeNotify     chan bool
}

func (r *RTCSession) close() {
	r.Caller.router.RemoveRTCSession(*r.Sid)
	r.Caller.UnCalling()
	r.Callee.UnCalling()
	r.Caller.rtcsession = nil
	r.Callee.rtcsession = nil
	if r.State == CALLING {
		r.closeNotify <- true
	}
	r.State = END
	close(r.CallerCandidate)
	close(r.CalleeCandidate)
	close(r.closeNotify)
}

func (r *RTCSession) offer(offer *Message) int {
	if r.State != INIT {
		return ERR_CALLING_STATE
	}
	//todo状态机机制
	offer.Mtype = RTC_OFFER
	offer.CallerSID = r.Caller.Sid
	//syslog.Println("发送主叫方Offer给被叫方", r.Sid, r.State, r.Caller.Member, offer.From, "->", r.Callee.Member, offer.To)
	r.Callee.Send(offer)
	r.State = CALLING
	return OK
}
func (r *RTCSession) candidate(candidate *Message) int {
	if r.State == INIT || r.State == END {
		return ERR_CALLING_STATE
	}
	candidate.Mtype = RTC_CANDIDATE
	if candidate.From == r.Caller.Member {
		r.CallerCandidate <- candidate
	} else if candidate.From == r.Callee.Member {
		r.CalleeCandidate <- candidate
	}
	return OK
}

func (r *RTCSession) answer(answer *Message) int {
	if r.State != CALLING {
		return ERR_CALLING_STATE
	}
	answer.Mtype = RTC_ANSWER
	answer.CallerSID = r.Caller.Sid
	//syslog.Println("发送被叫方Answer给主叫方", r.Sid, r.State, r.Caller.Member, answer.From, "->", r.Callee.Member, answer.To)
	r.Caller.Send(answer)
	//r.CalleeCandidate <- answer
	go r.exchange()
	return OK
}

// func (r *RTCSession) ack() int {
// 	if r.State != WAIT_ANSWER {
// 		return ERR_CALLING_STATE
// 	}
// 	r.State = CALLING
// 	go r.exchange()
// 	return OK
// }

func (r *RTCSession) bye(msg *Message) {
	if msg.From == r.Caller.Member {
		msg.Mtype = RTC_BYE
		r.Callee.Send(msg)
	} else if msg.From == r.Callee.Member {
		msg.Mtype = RTC_BYE
		r.Caller.Send(msg)
	}
	r.close()
}

func (r *RTCSession) exchange() {
	defer func() {
		syslog.Println("RTC通话结束", r.Sid, r.State, r.Caller.Member, "->", r.Callee.Member)
		if !r.Caller.IsOnline() {
			r.Caller.Close()
		}
		if !r.Callee.IsOnline() {
			r.Callee.Close()
		}
	}()
	syslog.Println("启动RTC通话交换CANDIDATE信息进程", r.Sid, r.State, r.Caller.Member, "->", r.Callee.Member)
	for {
		select {
		case <-r.closeNotify:
			return
		case msg, opened := <-r.CallerCandidate:
			if !opened {
				return
			}
			//syslog.Println("发送主叫方CANDIDATE给被叫方", r.Sid, r.State, r.Caller.Member, "->", r.Callee.Member)
			r.Callee.Send(msg)
		case msg, opened := <-r.CalleeCandidate:
			if !opened {
				return
			}
			//syslog.Println("发送被叫方CANDIDATE给主叫方", r.Sid, r.State, r.Caller.Member, "->", r.Callee.Member)
			r.Caller.Send(msg)
		case <-time.After(time.Second * 5):
			if !r.Caller.IsOnline() || !r.Callee.IsOnline() {
				//syslog.Println("通话双方有一方离线，关闭RTC通话进程", r.Sid, r.State, r.Caller.Member, r.Caller.IsOnline(), "->", r.Callee.Member, r.Callee.IsOnline())
				r.close()
				return
			}
		}
	}

}
